# -*- coding:utf-8 -*-
"""
@文件 auth.py
@Time : 2025/2/25
@Author: zjj
@Des:
@Email: 1065377805@qq.com

"""
from datetime import datetime, timedelta
from typing import Optional

import jwt
from fastapi import Depends, Request, HTTPException
from fastapi.security import OAuth2PasswordBearer, SecurityScopes
from jwt import PyJWTError
from pydantic import ValidationError
from starlette import status

from config import settings
from model.base import Admin, Access

OAuth2 = OAuth2PasswordBearer(settings.SWAGGER_UI_OAUTH2_REDIRECT_URL, scheme_name="Admin",
                              scopes={"is_admin": "超级管理员", "not_admin": "普通管理员"})
# 创建token
# def creat_token(data: dict):
#     to_encode = data.copy()
#     expire = datetime.now() + timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)
#     to_encode.update({"exp": expire})
#     encoded_token = jwt.encode(
#         to_encode,
#         settings.JWT_SECRET_KEY,
#         algorithm=settings.JWT_ALGORITHM
#     )
#     return encoded_token

# ... existing code ...

def creat_token(data: dict, expires_delta: Optional[timedelta] = None):
    """
    生成 JWT Token
    :param data: 需要加密的数据
    :param expires_delta: 过期时间
    :return:
    """
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
    return encoded_jwt



# 权限验证
async def check_permission(req:Request,security_scopes: SecurityScopes,token: str = Depends(OAuth2)):
    """
    权限验证
    :param req:
    :param security_scopes:
    :param token:
    :return:
    """
    try:
        payload = jwt.decode(
            token,
            settings.JWT_SECRET_KEY,
            algorithms=[settings.JWT_ALGORITHM]
        )
        if payload:
            user_id = payload.get("user_id",None)
            user_type = payload.get("user_type",None)
            if user_id is None or user_type is None:
                credentials_exception = HTTPException(
                    status_code=status.HTTP_401_UNAUTHORIZED,
                    detail="无效凭证1",
                    headers={"WWW-Authenticate": f"Bearer {token}"},
                )
                raise credentials_exception
        else:
            credentials_exception = HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效凭证2",
                headers={"WWW-Authenticate": f"Bearer {token}"},
            )
            raise credentials_exception
    except jwt.exceptions.ExpiredSignatureError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="凭证已经过期",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )
    except jwt.exceptions.InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效凭证3",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )
    except (PyJWTError,ValidationError):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效凭证4",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )
    # ---------------------------------------验证权限-------------------------------------------------------------------
    # 验证用户是否真是有效
    check_user = await Admin().get_or_none(id=user_id)
    if not check_user or check_user.user_status!=1:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="客户不存在或者已被管理员禁用，请联系管理人员",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )
    # 判断是否设置了权限域

    if security_scopes.scopes:
    # 非管理员且当前域需要验证
        if not user_type and security_scopes.scopes:
            # 查询用户是否有对应的权限
            is_pass = await Access.filter(
                role__user__id=user_id,
                is_check=True,
                scopes__in=set(security_scopes.scopes)).all()
            if not is_pass:
                raise HTTPException(
                    status_code=status.HTTP_401_UNAUTHORIZED,
                    detail="没有权限访问",
                    headers={"WWW-Authenticate": security_scopes.scope_str},
                )
    # 缓存用户id

    req.state.user_id = user_id
    req.state.user_type = user_type



# 解析token
# def get_token(token: str = Depends(creat_token)):
#     payload = jwt.decode(
#         token,
#         settings.SECRET_KEY,
#         algorithms=[settings.JWT_ALGORITHM]
#     )
#     return payload
